package com.sl.biz.modular.process.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.sl.biz.core.runner.loader.DatabaseProcessPluginLoader;
import com.sl.biz.modular.process.controller.request.ProcessCompObjectRebuildRequest;
import com.sl.biz.modular.process.controller.request.ProcessCompVersionRebuildRequest;
import com.sl.biz.modular.process.controller.request.ProcessCompVersionSaveRequest;
import com.sl.biz.modular.process.dao.domain.dto.ProcessCompObjectDTO;
import com.sl.biz.modular.process.dao.domain.dto.ProcessCompVersionBuildDTO;
import com.sl.biz.modular.process.dao.domain.dto.ProcessCompVersionDTO;
import com.sl.biz.modular.process.dao.domain.entity.ProcessCompDO;
import com.sl.biz.modular.process.dao.domain.entity.ProcessCompObjectDO;
import com.sl.biz.modular.process.dao.domain.entity.ProcessCompVersionDO;
import com.sl.biz.modular.process.dao.service.ProcessCompVersionBuildDaoService;
import com.sl.biz.modular.process.dao.service.ProcessCompVersionDaoService;
import com.sl.biz.modular.process.helper.ProcessCompObjectInitFileHelper;
import com.sl.biz.modular.process.service.ProcessCompObjectBizService;
import com.sl.biz.modular.process.service.ProcessCompVersionBizService;
import com.sl.common.enums.CommonDsiableFlagEnum;
import com.sl.common.util.Assert;
import com.sl.core.engine.ProcessEngine;
import com.sl.core.engine.plugin.ProcessPluginLoaderManager;
import com.sl.core.engine.plugin.ProcessPluginRegistry;
import com.sl.core.engine.plugin.domain.PluginDecorate;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Map;


@Service
@Slf4j
@RequiredArgsConstructor
public class ProcessCompVersionBizServiceImpl implements ProcessCompVersionBizService {

    private final ProcessCompVersionDaoService compVersionDaoService;

    private final ProcessCompVersionBuildDaoService versionBuildDaoService;

    private final ProcessCompObjectBizService compObjectBizService;

    private final DatabaseProcessPluginLoader databaseProcessPluginLoader;

    @Override
    public List<ProcessCompVersionDTO> list(ProcessCompVersionDO processCompVersionDO) {
        List<ProcessCompVersionDTO> list = compVersionDaoService.queryList(processCompVersionDO);

        if (ObjectUtil.isNull(list)) {
            list = Lists.newArrayList();
        }
        List<PluginDecorate> pluginDecorates = ProcessPluginLoaderManager.INSTANCE.matchPluginList(processCompVersionDO.getCompCode());
        if (CollUtil.isNotEmpty(pluginDecorates)) {
            for (PluginDecorate pluginDecorate : pluginDecorates) {
                String version = pluginDecorate.getVersion();
                String pluginCode = pluginDecorate.getPluginCode();
                String orgId = pluginDecorate.getOrgId();

                long count = list.stream().filter(v ->
                        ObjectUtil.equal(version, v.getCompVersion())
                                && ObjectUtil.equal(pluginCode, v.getCompCode())
                                && ObjectUtil.equal(orgId, v.getOrgId())).count();

                if (count > 0) {
                    continue;
                }

                ProcessCompVersionDTO processCompVersionDTO = new ProcessCompVersionDTO();
                processCompVersionDTO.setId(IdUtil.nanoId());
                processCompVersionDTO.setCompCode(pluginDecorate.getPluginCode());
                processCompVersionDTO.setCompVersion(pluginDecorate.getVersion());
                processCompVersionDTO.setCompDesc(pluginDecorate.getDesc());
                processCompVersionDTO.setDisableFlag(0);
                processCompVersionDTO.setSystemFlag(pluginDecorate.getSystemFlag());
                processCompVersionDTO.setBuildStatus(2);
                list.add(processCompVersionDTO);
            }
        }


        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
//        List<String> compCodeList = Lists.newArrayList();
//        List<String> compVersionList = Lists.newArrayList();

        for (ProcessCompVersionDTO processCompVersionDTO : list) {
//            compCodeList.add(processCompVersionDTO.getCompVersion());
//            compVersionList.add(processCompVersionDTO.getCompCode());
            String compVersion = processCompVersionDTO.getCompVersion();
            String compCode = processCompVersionDTO.getCompCode();
            ProcessCompVersionBuildDTO processCompVersionBuildDTO = versionBuildDaoService.queryLastBuild(compCode, compVersion);
            if (ObjectUtil.isNotNull(processCompVersionBuildDTO)) {
                processCompVersionDTO.setBuildStatus(processCompVersionBuildDTO.getBuildStatus());
            }
        }
        return list;
    }

    @Override
    public Boolean save(ProcessCompVersionSaveRequest processComp) {
        String id = processComp.getId();

        if (StrUtil.isNotBlank(id)) {
            ProcessCompVersionDO byId = compVersionDaoService.getById(id);
            processComp.setDisableFlag(byId.getDisableFlag());
            boolean b = compVersionDaoService.updateById(processComp);
            return b;
        }
        //默认是停用的
        processComp.setDisableFlag(1);
        boolean save = compVersionDaoService.save(processComp);


        //需要初始化一把demo包
        ProcessCompObjectDO processCompObjectDO = new ProcessCompObjectDO();
        processCompObjectDO.setCompVersion(processComp.getCompVersion());
        processCompObjectDO.setCompCode(processComp.getCompCode());
        processCompObjectDO.setCompFile(ProcessCompObjectInitFileHelper.INSTANCE.initCompFile(processComp.getCompCode(), processComp.getCompDesc(), processComp.getCompVersion()));
        //构建demo包

        compObjectBizService.save(processCompObjectDO);
        return save;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean setStatusFlag(ProcessCompVersionDO assertUserUse) {
        //判断构建状态，如果是没构建，不允许启用
        ProcessCompVersionDO processCompVersionDO = compVersionDaoService.getById(assertUserUse);
        Assert.isTrue(ObjectUtil.isNull(processCompVersionDO), "获取版本信息失败");

        ProcessEngine.INSTANCE.clearPool();
        Integer disableFlag = assertUserUse.getDisableFlag();
        if (ObjectUtil.equal(disableFlag, 0)) {
            ProcessCompVersionBuildDTO processCompVersionBuildDTO = versionBuildDaoService.queryLastBuild(processCompVersionDO.getCompCode(), processCompVersionDO.getCompVersion());
            Assert.isTrue(ObjectUtil.isNull(processCompVersionBuildDTO), "未获取到构建状态，不能启用");
            Assert.isTrue(!ObjectUtil.equal(processCompVersionBuildDTO.getBuildStatus(), 2), "构建状态错误，不能启用");
        } else {
            //todo  停用要校验是否有插件使用，如果有的话是不能停用的

            //卸载插件
            databaseProcessPluginLoader.remove(processCompVersionDO.getOrgId(),
                    processCompVersionDO.getCompCode(), processCompVersionDO.getCompVersion());
        }
        Boolean b = compVersionDaoService.setStatusFlag(assertUserUse);

        //状态插件
        if (ObjectUtil.equal(disableFlag, 0)) {
            Map<String, List<PluginDecorate>> init = databaseProcessPluginLoader.init(processCompVersionDO.getOrgId(), processCompVersionDO.getCompCode(), processCompVersionDO.getCompVersion());
            if (MapUtil.isNotEmpty(init)) {
                List<PluginDecorate> pluginDecorates = CollUtil.get(init.values(), 0);
                //todo 这里的最新版本是需要处理的。匹配是不是最新的一个版本来设置
                ProcessPluginRegistry.INSTANCE.registerByPluginDecorate(CollUtil.get(pluginDecorates, 0), false);
            }
        }

        return b;
    }

    @Override
    public ProcessCompVersionDTO getById(ProcessCompVersionDO addRequest) {
        return BeanUtil.copyProperties(compVersionDaoService.getById(addRequest.getId()), ProcessCompVersionDTO.class);
    }


    @Override
    public Boolean rebuild(ProcessCompVersionRebuildRequest processComp) {

        ProcessCompVersionDO byId = compVersionDaoService.getById(processComp.getId());
        if (ObjectUtil.isNull(byId)) {
            return Boolean.FALSE;
        }
        Integer disableFlag = byId.getDisableFlag();
        Assert.isTrue(ObjectUtil.equal(disableFlag, CommonDsiableFlagEnum.ENABLE_FLAG), "启用的不能构建，请先停用");
//        ProcessCompObjectDTO byId = this.compObjectDaoService.queryByCodeAndVersion(processComp.getCompCode(),processComp.getCompVersion());
//
//        return saveAndRebuild(byId);
        ProcessCompObjectRebuildRequest processCompObjectDO = new ProcessCompObjectRebuildRequest();
        processCompObjectDO.setCompCode(byId.getCompCode());
        processCompObjectDO.setCompVersion(byId.getCompVersion());
        processCompObjectDO.setTid(processComp.getTid());
        Boolean rebuild = compObjectBizService.rebuild(processCompObjectDO);
        return rebuild;
    }

    @Override
    public Boolean removeById(ProcessCompVersionDO assertUserUse) {

        ProcessCompVersionDO byId = compVersionDaoService.getById(assertUserUse.getId());
        if (ObjectUtil.isNull(byId)) {
            return Boolean.FALSE;
        }
        Integer disableFlag = byId.getDisableFlag();
        Assert.isTrue(ObjectUtil.equal(disableFlag, CommonDsiableFlagEnum.ENABLE_FLAG), "启用的不能删除，请先停用");

        compVersionDaoService.removeById(byId.getId());

        ProcessCompObjectDO processCompObjectDO = new ProcessCompObjectDO();
        processCompObjectDO.setCompCode(assertUserUse.getCompCode());
        processCompObjectDO.setCompVersion(assertUserUse.getCompVersion());
        compObjectBizService.removeByCompCodeAndVersion(processCompObjectDO);

        return Boolean.TRUE;
    }
}
